﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using ShanNiang.AutoUpdate.Service;
using ShanNiang.AutoUpdate.Service.Implementations;
using ShanNiang.Hosting;
using ShanNiang.Mvvm.Tools;
using ShanNiang.Mvvm.UiServices;
using ShanNiang.Mvvm.ViewModels;
using ShanNiang.Packing.UserControls;
using ShanNiang.Service;
using ShanNiang.Service.Constants;
using System.IO;
using System.Runtime.Versioning;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;

namespace ShanNiang.Packing
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    [SupportedOSPlatform("windows")]
    public partial class App : Application
    {
        static Mutex? _mutex;
        [STAThread]
        static void Main(string[] args)
        {
            var AppDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            Log.Logger = new LoggerConfiguration()
                    .MinimumLevel.Debug()
                    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                    .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
                    .MinimumLevel.Override("System", LogEventLevel.Warning)
                    .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
                    .Enrich.FromLogContext()
                    .WriteTo.File(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", path: Path.Combine(AppDataFolder, "/SnSoft/XkmWork/Logs/Log_Main-.txt") , rollingInterval: RollingInterval.Day, retainedFileCountLimit: 2)
                    .CreateLogger();
            if (CheckMutex())
            {
                Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", Path.Combine(AppDataFolder, CommonData.WebView2DataFolder));
                try
                {
                    Log.Debug("创建 Hosting...");
                    using var host = CreateHostBuilder(args).Build();
                    host.Start();
                    Log.Debug("启动了 Hosting...");
                    var app = new App();
                    app.InitializeComponent();
                    app.MainWindow = host.Services.GetRequiredService<MainWindow>();
                    app.MainWindow.Show();
                    Log.Debug("保存Window状态到共享内存");
                    WinApis.SaveWindowHandle(new WindowInteropHelper(app.MainWindow).Handle);
                    Log.Debug("关闭输入法 Hosting...");
                    InputMethod.Current.ImeState = InputMethodState.Off;
                    Log.Debug("注册全局异常处理");
                    app.RegisterEvents();
                    app.Run();
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "发生异常");
                }
            }
            DisposeMutex();
        }
        /// <summary>
        /// 检测 Mutex
        /// </summary>
        /// <returns></returns>
        static bool CheckMutex()
        {
            Log.Logger.Information($"检测是否有运行的实例");
            _mutex = new Mutex(true, CommonData.ApplicationMutexName, out bool createdNew);
            if (!createdNew)
            {
                Log.Logger.Information($"已有实例运行");
                IntPtr hWnd = WinApis.GetExistingWindowHandle();
                if (hWnd != IntPtr.Zero)
                {
                    Log.Logger.Information($"窗体句柄：{hWnd}");
                    // 激已有窗口
                    WinApis.ShowWindow(hWnd, 9); // SW_RESTORE = 9
                    WinApis.SetForegroundWindow(hWnd);
                }
            }
            Log.Logger.Information($"无实例运行");
            return createdNew;
        }
        /// <summary>
        /// 释放
        /// </summary>
        static void DisposeMutex()
        {
            if (_mutex != null)
            {
                _mutex.Close();
            }
        }
        /// <summary>
        /// 创建和配置主机
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        static IHostBuilder CreateHostBuilder(string[] args)
        {
            //var windwosAssembly = Assembly.Load(LocalWindowsAssemblyName);
            //var servicesAssembly = Assembly.Load(LocalServiceAssemblyName);
            var hostBuilder = Host.CreateDefaultBuilder(args);
            hostBuilder.ConfigureAppConfiguration(HostingExtensions.UseConfiguration);
            hostBuilder.ConfigureServices((context, services) =>
            {
                services.AddAutoMapper(typeof(AutoMapperConfiguration));
                //加载本地服务
                services.AddLocalServices(context.Configuration, typeof(CommonData).Assembly);
                //添加本地窗体
                services.AddLocalWindows(context.Configuration, typeof(MainWindow).Assembly);
                //添加本地用户控件
                services.AddLocalUserControls(context.Configuration, typeof(PackBoxControl).Assembly);
                //添加UI可以使用的ViewModel
                services.AddLocalCostomServices(context.Configuration, typeof(UIViewModel).Assembly, typeof(UIViewModel));
                //添加消息和声音服务
                services.AddSingleton<IUiService, UiService>();
                //添加升级服务
                services.AddHostedService<CheckVersionService>();


                //配置其他配置
                services.AddSingleton(context.Configuration.GetSection("AutoUpdateConfig").Get<AutoUpdateConfig>() ?? new AutoUpdateConfig());
                services.AddSingleton(context.Configuration.GetSection("PackingConfig").Get<PackingConfig>() ?? new PackingConfig());
                services.AddSingleton(context.Configuration.GetSection("ScanSoundsConfig").Get<ScanSoundsConfig>() ?? new ScanSoundsConfig());
                services.AddSingleton<UserContext>();

                //services.AddSingleton<IMessenger, WeakReferenceMessenger>();
                services.AddSingleton(_ => Current.Dispatcher);
            });
            hostBuilder.UseSerilog((ctx, lc) => lc.ReadFrom.Configuration(ctx.Configuration));
            return hostBuilder;
        }


    }
}
